import {Component, OnDestroy, OnInit} from '@angular/core';
import {FormGroup, FormControl, FormBuilder, FormArray} from '@angular/forms';
import {CommonService} from './../shared/service/common.service';
import {Subscription} from 'rxjs';

@Component({
  selector: 'app-main',
  templateUrl: './main.component.html',
  styleUrls: ['./main.component.scss']
})
export class MainComponent implements OnInit, OnDestroy {

  // 表单初始化
  profileForm = new FormGroup({
    firstName: new FormControl(''),
    lastName: new FormControl(''),
    address: new FormGroup({
      street: new FormControl(''),
      city: new FormControl(''),
      state: new FormControl('')
    }),
    information: new FormGroup({
      height: new FormControl({value: '', disabled: true}),
      age: new FormControl({value: '', disabled: false}),
      gender: new FormControl({value: '', disabled: true})
    }),
    aliases: this.fb.array([
      new FormControl('')
    ])
  });

  // 下拉选择框的数据列表
  dropdownDataList = {
    formGroup: [{
      title: 'profileForm',
      key: 'profileForm',
      selectable: true,
      children: []
    }],
    formControl: [{
      title: 'profileForm',
      key: 'profileForm1',
      selectable: false,
      children: []
    }],
    formArray: [],

    // 默认展开树节点
    formGroupExpandKeys: ['profileForm'],
    formControlExpandKeys: ['profileForm1']
  };

  // 选中的表单类型字符串
  selectedFormStr = {
    formGroup: 'profileForm',
    formControl: 'firstName',
    formArray: 'aliases'
  };

  // 选中的表单类型对象
  selectedFormObj = {
    formGroup: null,
    formControl: null,
    formArray: null
  };

  // 表单层级关系
  relationShip = [{
    name: 'profileForm',
    parent: null
  }];

  formNodeSubscription = new Subscription();

  get aliases() {
    return this.profileForm.get('aliases') as FormArray;
  }

  constructor(
    private fb: FormBuilder,
    private commonService: CommonService
  ) {
    this.listenEvents();
  }

  ngOnInit() {
    this.commonService.formInst = this.profileForm;
    this.createFormTree(this.profileForm.controls, this.dropdownDataList['formGroup'][0]['children'], this.dropdownDataList['formControl'][0]['children'], 'profileForm');
    this.commonService.formTree = this.dropdownDataList;
    this.commonService.relationShip = this.relationShip;

    this.commonService.formTreeSubject.next(this.dropdownDataList);
    // console.log(this.profileForm.controls['address']);
    // this.profileForm.get('firstName').setParent(this.profileForm.controls['address']);
    // console.log(this.profileForm);

    for (const key of Object.keys(this.selectedFormStr)) {
      this.commonService.getFormNodeInstance(key, this.selectedFormStr[key]);
    }
  }

  ngOnDestroy() {
    this.formNodeSubscription.unsubscribe();
  }

  /**
   * 生成form表单的树状结构
   * @param controls(Array) ：当前FormGroup下的controls数组
   * @param formGroupChildren(Array) ：当前formGroup树节点的children属性
   * @param formControlChildren(Array) ：当前formControl树节点的children属性
   */
  createFormTree(controls, formGroupChildren, formControlChildren, parentName) {
    for (const key of Object.keys(controls)) {
      const childNode = controls[key];
      const treeObj = {
        title: key,
        key,
        selectable: true
      };

      this.relationShip.push({
        name: key,
        parent: parentName
      });
      if (childNode['controls']) {
        // 如果子节点下的controls里全是FormControl类型，那么FormGroup树则判定它为叶子节点
        if (Object.values(childNode['controls']).every(control => {
          return control instanceof FormControl;
        })) {
          treeObj['isLeaf'] = true;
        } else {
          treeObj['children'] = [];
        }
        formGroupChildren.push(treeObj);
        this.dropdownDataList.formGroupExpandKeys.push(key);

        // FormControl树暂时只生成FormGroup和FormControl类型，不支持FormArray类型
        if (childNode instanceof FormGroup) {
          const treeObj1 = JSON.parse(JSON.stringify(treeObj));
          treeObj1['key'] = key + '1';
          treeObj1['children'] = [];
          treeObj1['selectable'] = false;
          delete treeObj1.isLeaf;
          formControlChildren.push(treeObj1);
          this.dropdownDataList.formControlExpandKeys.push(key + '1');
          this.createFormTree(childNode['controls'], formGroupChildren[formGroupChildren.length - 1]['children'], formControlChildren[formControlChildren.length - 1]['children'], key);
        }
      } else {
        treeObj['isLeaf'] = true;
        formControlChildren.push(treeObj);
      }
    }
  }

  /**
   * 将控件信息存储在公共service里
   * @param type(string) ：类型， 有三种： formGroup、formControl、formArray
   */
  saveControlInfo(type) {
    const controlInfo = {
      name: this.selectedFormStr[type],
      instantiation: this.selectedFormObj[type]
    };

    switch (type) {
      case 'formControl':
        this.commonService.formControlInst = controlInfo;
        this.commonService.formControlSubject.next(this.commonService.formControlInst);
        break;

      case 'formGroup':
        this.commonService.formGroupInst = controlInfo;
        this.commonService.formGroupSubject.next(this.commonService.formGroupInst);
        break;

      case 'formArray':
        this.commonService.formArrayInst = controlInfo;
        this.commonService.formArraySubject.next(this.commonService.formArrayInst);
        break;
    }
  }

  addAlias() {
    this.aliases.push(new FormControl(''));
    const aliasesLength = this.aliases.controls.length - 1;
    this.dropdownDataList['formControl'][0]['children'][4]['children'].push({
      title: 'Alias' + aliasesLength,
      key: 'alias' + aliasesLength,
      isLeaf: true
    });
  }

  // 监听FormGroup下拉框变化
  handleFormGroupChange(name) {
    this.commonService.getFormNodeInstance('formGroup', name);
  }

  // 监听FormControl下拉框变化
  handleFormControlChange(name) {
    this.commonService.getFormNodeInstance('formControl', name);
  }

  /**
   * 监听subscribe事件
   */
  listenEvents() {
    this.formNodeSubscription = this.commonService.formNodeSubject.subscribe(nodeObj => {
      this.selectedFormObj[nodeObj['type']] = nodeObj['instance'];
      this.saveControlInfo(nodeObj['type']);
    });
  }
}
